package com.bridgeintelligent.tag.webserver.dim.mgmt.service.export.excel;

import com.bridgeintelligent.tag.constants.ExceptionCodes;
import com.bridgeintelligent.tag.mapper.CatalogMapper;
import com.bridgeintelligent.tag.mapper.DimAggMapper;
import com.bridgeintelligent.tag.webserver.dim.mgmt.api.DimCatalog;
import com.bridgeintelligent.tag.webserver.dim.mgmt.api.DimException;
import com.bridgeintelligent.tag.webserver.dim.mgmt.api.export.ExcelCatalogModel;
import com.bridgeintelligent.tag.webserver.dim.mgmt.api.export.ExcelDimDataModel;
import com.bridgeintelligent.tag.webserver.dim.mgmt.service.catalog.ICatalogService;
import com.wayneleo.quickstart.framework.BaseException;
import com.wayneleo.quickstart.framework.ExceptionCode;
import com.wayneleo.quickstart.framework.IDGenerator;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author JackCheung
 * @date 2020/7/20 11:53 AM.
 * description:
 */
@Slf4j
@AllArgsConstructor
@Service
public class DimExcelDimCatalogServiceImpl implements IDimExcelDimCatalogService {

    private DimAggMapper dimAggMapper;
    private CatalogMapper catalogMapper;

    /**
     * 找到所有标签目录中文名对应的id，并且创建不存在的标签目录，并给excel数据赋目录值
     *
     * @param dimDataModelList List<ExcelDimDataModel> dimDataModelList
     */
    @Override
    public void createCatalog(List<ExcelDimDataModel> dimDataModelList) {
        List<ExcelCatalogModel> firstCatalogList = firstCatalogHandler(dimDataModelList);
        secondCatalogHandler(firstCatalogList, dimDataModelList);
        Map<String, DimCatalog> catalogMap = fetchCatalog();
        Map<String, String> map = new HashMap<>(catalogMap.size());
        catalogMap.forEach((k, v) -> {
            if (2 == v.getLevel()) {
                String key = v.getName() + catalogMap.get(v.getParentId())
                                                     .getName();
                map.put(key, v.getId());
            }
        });
        dimDataModelList.forEach(dimDataModel -> {
            String name = dimDataModel.getSecondCatalog() + dimDataModel.getFirstCatalog();
            String id = map.get(name);
            dimDataModel.setCatalogId(id);
        });
    }

    @Override
    public Map<String, DimCatalog> fetchCatalog() {
        return catalogMapper.findCatalogList()
                            .stream()
                            .collect(Collectors.toMap(DimCatalog::getId, Function.identity(), (v1, v2) -> v1));
    }

    /**
     * secondCatalogHandler
     *
     * @param firstCatalogList firstCatalogList
     * @param dimDataModelList dimDataModelList
     * @return 二级目录名称id对应map
     */
    private Map<String, String> secondCatalogHandler(List<ExcelCatalogModel> firstCatalogList, List<ExcelDimDataModel> dimDataModelList) {
        List<String> secondCatalogNames = dimDataModelList.stream()
                                                          .filter(dimDataModel -> StringUtils.isNotEmpty(dimDataModel.getFirstCatalog()) &&
                                                                  StringUtils.isNotEmpty(dimDataModel.getSecondCatalog()))
                                                          .map(excelData -> excelData.getFirstCatalog() + SIGN +
                                                                  excelData.getSecondCatalog())
                                                          .distinct()
                                                          .collect(Collectors.toList());
        Map<String, String> secondNameToFirstNameMap = new HashMap<>(secondCatalogNames.size());
        secondCatalogNames.forEach(s -> secondNameToFirstNameMap.put(s, StringUtils.substringBefore(s, SIGN)));
        Map<String, String> firstNameToIdeMap = firstCatalogList.stream()
                                                                .collect(Collectors.toMap(ExcelCatalogModel::getName,
                                                                                          ExcelCatalogModel::getId));
        Map<String, String> firstIdToNameMap = firstCatalogList.stream()
                                                               .collect(Collectors.toMap(ExcelCatalogModel::getId,
                                                                                         ExcelCatalogModel::getName));
        List<ExcelCatalogModel> secondCatalogList = dimAggMapper.findCatalogListSecond(secondCatalogNames.stream()
                                                                                                         .map(s -> StringUtils.substringAfter(
                                                                                                                 s,
                                                                                                                 SIGN))
                                                                                                         .collect(Collectors.toList()));
        List<String> exitsCatalog = secondCatalogList.stream()
                                                     .map(excelCatalogModel -> firstIdToNameMap.get(excelCatalogModel.getParentId()) +
                                                             SIGN + excelCatalogModel.getName())
                                                     .collect(Collectors.toList());
        secondCatalogNames.removeAll(exitsCatalog);
        Integer max = catalogMapper.findMaxNumberInLevel(SECOND);
        if (max == null) {
            max = 1;
        }
        AtomicInteger atomicInteger = new AtomicInteger(max);
        if (CollectionUtils.isNotEmpty(secondCatalogNames)) {
            secondCatalogNames.forEach(name -> {
                String catalogName = StringUtils.substringAfter(name, SIGN);
                if ( catalogMapper.findByCataName( catalogName ) != null ) {
                    throw new BaseException( new ExceptionCode( 999, "标签目录名称重复: " + catalogName ) );
                }
                catalogMapper.add(IDGenerator.gen(),
                    catalogName,
                    firstNameToIdeMap.get(secondNameToFirstNameMap.get(name)),
                    atomicInteger.getAndIncrement(),
                    2);
        });
        }
        return secondCatalogList.stream()
                                .collect(Collectors.toMap(ExcelCatalogModel::getName,
                                                          ExcelCatalogModel::getId,
                                                          (oldValue, newValue) -> newValue));
    }

    /**
     * firstCatalogHandler
     *
     * @param dimDataModelList dimDataModelList
     * @return 所有一级目录in
     */
    private List<ExcelCatalogModel> firstCatalogHandler(List<ExcelDimDataModel> dimDataModelList) {
        List<String> firstCatalogNames = dimDataModelList.stream()
                                                         .filter(dimDataModel -> StringUtils.isNotEmpty(dimDataModel.getFirstCatalog()))
                                                         .map(ExcelDimDataModel::getFirstCatalog)
                                                         .distinct()
                                                         .collect(Collectors.toList());
        if(CollectionUtils.isEmpty(firstCatalogNames)){
            throw new DimException(ExceptionCodes.EXPORT_70006);
        }
        List<ExcelCatalogModel> firstCatalogList = dimAggMapper.findCatalogList(firstCatalogNames, FIRST);
        Integer max = catalogMapper.findMaxNumberInLevel(FIRST);
        AtomicInteger atomicInteger = new AtomicInteger( max == null ? 1 : max );
        //取差集
        firstCatalogNames.removeAll(firstCatalogList.stream()
                                                    .map(ExcelCatalogModel::getName)
                                                    .collect(Collectors.toList()));
        //创建不存在一级目录
        if (CollectionUtils.isNotEmpty(firstCatalogNames)) {
            List<ExcelCatalogModel> createdFirst = firstCatalogNames.stream()
                                                    .map(name -> new ExcelCatalogModel(name, IDGenerator.gen(), 1))
                                                    .peek(excelCatalogModel -> {
                                                        if ( catalogMapper.findByCataName( excelCatalogModel.getName() ) != null ) {
                                                            throw new BaseException(
                                                                new ExceptionCode( 999, "标签目录名称重复: "
                                                                                            + excelCatalogModel.getName() ) );
                                                        }
                                                        catalogMapper.add(excelCatalogModel.getId(),
                                                            excelCatalogModel.getName(),
                                                            ICatalogService.PARENT_ID,
                                                            atomicInteger.getAndIncrement(),
                                                            excelCatalogModel.getLevel());
                                                    })
                                                    .collect(Collectors.toList());
            firstCatalogList.addAll(createdFirst);
        }
        return firstCatalogList;
    }
}
